package com.yupi.yupicturebackend.utils;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.yupi.yupicturebackend.model.dto.game.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.*;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 图片游戏化和互动工具类
 * 
 * <p>提供图片拼图游戏、找茬游戏、AR滤镜、虚拟试穿等娱乐互动功能</p>
 * 
 * @author yupi
 */
@Slf4j
@Component
public class GameInteractionUtils {

    /**
     * 创建拼图游戏
     *
     * @param imageUrl 原图URL
     * @param puzzleConfig 拼图配置
     * @return 拼图游戏数据
     */
    public static PuzzleGameResult createPuzzleGame(String imageUrl, PuzzleConfig puzzleConfig) {
        try {
            log.info("创建拼图游戏: {}x{}", puzzleConfig.getRows(), puzzleConfig.getCols());
            
            BufferedImage originalImage = ImageIO.read(new URL(imageUrl));
            
            // 1. 切割图片
            List<PuzzlePiece> pieces = cutImageIntoPieces(originalImage, puzzleConfig);
            
            // 2. 打乱拼图块
            Collections.shuffle(pieces);
            
            // 3. 生成游戏数据
            PuzzleGameData gameData = new PuzzleGameData();
            gameData.setGameId(IdUtil.fastSimpleUUID());
            gameData.setOriginalImageUrl(imageUrl);
            gameData.setPieces(pieces);
            gameData.setRows(puzzleConfig.getRows());
            gameData.setCols(puzzleConfig.getCols());
            gameData.setDifficulty(puzzleConfig.getDifficulty());
            gameData.setCreateTime(LocalDateTime.now());
            
            // 4. 生成预览图
            byte[] previewImage = generatePuzzlePreview(pieces, puzzleConfig);
            
            PuzzleGameResult result = new PuzzleGameResult();
            result.setSuccess(true);
            result.setGameData(gameData);
            result.setPreviewImage(previewImage);
            result.setEstimatedTime(calculateEstimatedTime(puzzleConfig));
            result.setMaxScore(calculateMaxScore(puzzleConfig));
            
            return result;
            
        } catch (Exception e) {
            log.error("创建拼图游戏失败: {}", imageUrl, e);
            return createPuzzleErrorResult("创建失败: " + e.getMessage());
        }
    }

    /**
     * 创建找茬游戏
     *
     * @param imageUrl 原图URL
     * @param spotConfig 找茬配置
     * @return 找茬游戏数据
     */
    public static SpotDifferenceResult createSpotDifferenceGame(String imageUrl, SpotDifferenceConfig spotConfig) {
        try {
            log.info("创建找茬游戏: {} 个差异点", spotConfig.getDifferenceCount());
            
            BufferedImage originalImage = ImageIO.read(new URL(imageUrl));
            
            // 1. 生成差异图片
            BufferedImage modifiedImage = createModifiedImage(originalImage, spotConfig);
            
            // 2. 记录差异点位置
            List<DifferencePoint> differences = generateDifferences(originalImage, spotConfig);
            
            // 3. 转换为字节数组
            byte[] originalImageData = imageToBytes(originalImage);
            byte[] modifiedImageData = imageToBytes(modifiedImage);
            
            // 4. 创建游戏数据
            SpotDifferenceGameData gameData = new SpotDifferenceGameData();
            gameData.setGameId(IdUtil.fastSimpleUUID());
            gameData.setOriginalImageUrl(imageUrl);
            gameData.setOriginalImageData(originalImageData);
            gameData.setModifiedImageData(modifiedImageData);
            gameData.setDifferences(differences);
            gameData.setDifficultyLevel(spotConfig.getDifficulty());
            gameData.setTimeLimit(spotConfig.getTimeLimit());
            gameData.setCreateTime(LocalDateTime.now());
            
            SpotDifferenceResult result = new SpotDifferenceResult();
            result.setSuccess(true);
            result.setGameData(gameData);
            result.setHints(generateHints(differences));
            result.setMaxScore(differences.size() * 100);
            
            return result;
            
        } catch (Exception e) {
            log.error("创建找茬游戏失败: {}", imageUrl, e);
            return createSpotDifferenceErrorResult("创建失败: " + e.getMessage());
        }
    }

    /**
     * 创建AR滤镜
     *
     * @param filterConfig AR滤镜配置
     * @return AR滤镜数据
     */
    public static ARFilterResult createARFilter(ARFilterConfig filterConfig) {
        try {
            log.info("创建AR滤镜: {}", filterConfig.getFilterName());
            
            // 1. 生成滤镜效果参数
            ARFilterData filterData = new ARFilterData();
            filterData.setFilterId(IdUtil.fastSimpleUUID());
            filterData.setFilterName(filterConfig.getFilterName());
            filterData.setFilterType(filterConfig.getFilterType());
            filterData.setEffectParameters(generateEffectParameters(filterConfig));
            filterData.setFaceTrackingEnabled(filterConfig.isEnableFaceTracking());
            filterData.setHandTrackingEnabled(filterConfig.isEnableHandTracking());
            
            // 2. 生成3D模型数据（如果需要）
            if (filterConfig.isUse3DModel()) {
                filterData.setModel3DData(generate3DModelData(filterConfig));
            }
            
            // 3. 生成着色器代码
            String vertexShader = generateVertexShader(filterConfig);
            String fragmentShader = generateFragmentShader(filterConfig);
            filterData.setVertexShader(vertexShader);
            filterData.setFragmentShader(fragmentShader);
            
            // 4. 生成预览图
            byte[] previewImage = generateFilterPreview(filterConfig);
            
            ARFilterResult result = new ARFilterResult();
            result.setSuccess(true);
            result.setFilterData(filterData);
            result.setPreviewImage(previewImage);
            result.setCompatiblePlatforms(Arrays.asList("iOS", "Android", "Web"));
            result.setCreateTime(LocalDateTime.now());
            
            return result;
            
        } catch (Exception e) {
            log.error("创建AR滤镜失败: {}", filterConfig.getFilterName(), e);
            return createARFilterErrorResult("创建失败: " + e.getMessage());
        }
    }

    /**
     * 创建虚拟试穿
     *
     * @param userImageUrl 用户图片URL
     * @param clothingConfig 服装配置
     * @return 虚拟试穿结果
     */
    public static VirtualTryOnResult createVirtualTryOn(String userImageUrl, VirtualTryOnConfig clothingConfig) {
        try {
            log.info("创建虚拟试穿: {}", clothingConfig.getClothingType());
            
            BufferedImage userImage = ImageIO.read(new URL(userImageUrl));
            
            // 1. 人体姿态检测
            List<BodyKeypoint> bodyKeypoints = detectBodyPose(userImage);
            
            // 2. 服装适配
            BufferedImage clothingImage = loadClothingImage(clothingConfig.getClothingImageUrl());
            BufferedImage fittedClothing = fitClothingToBody(clothingImage, bodyKeypoints, clothingConfig);
            
            // 3. 图像合成
            BufferedImage resultImage = compositeImages(userImage, fittedClothing, bodyKeypoints);
            
            // 4. 后处理优化
            BufferedImage finalImage = postProcessTryOn(resultImage, clothingConfig);
            
            VirtualTryOnResult result = new VirtualTryOnResult();
            result.setSuccess(true);
            result.setTryOnId(IdUtil.fastSimpleUUID());
            result.setOriginalImageUrl(userImageUrl);
            result.setResultImage(imageToBytes(finalImage));
            result.setBodyKeypoints(bodyKeypoints);
            result.setClothingInfo(clothingConfig);
            result.setFitScore(calculateFitScore(bodyKeypoints, clothingConfig));
            result.setCreateTime(LocalDateTime.now());
            
            return result;
            
        } catch (Exception e) {
            log.error("虚拟试穿失败: {}", userImageUrl, e);
            return createVirtualTryOnErrorResult("试穿失败: " + e.getMessage());
        }
    }

    /**
     * 创建图片记忆游戏
     *
     * @param imageUrls 图片URL列表
     * @param memoryConfig 记忆游戏配置
     * @return 记忆游戏数据
     */
    public static MemoryGameResult createMemoryGame(List<String> imageUrls, MemoryGameConfig memoryConfig) {
        try {
            log.info("创建图片记忆游戏: {} 张图片", imageUrls.size());
            
            // 1. 选择游戏图片
            List<String> selectedImages = selectGameImages(imageUrls, memoryConfig.getCardCount() / 2);
            
            // 2. 创建卡片对
            List<MemoryCard> cards = createMemoryCards(selectedImages);
            
            // 3. 打乱卡片顺序
            Collections.shuffle(cards);
            
            // 4. 生成游戏数据
            MemoryGameData gameData = new MemoryGameData();
            gameData.setGameId(IdUtil.fastSimpleUUID());
            gameData.setCards(cards);
            gameData.setDifficulty(memoryConfig.getDifficulty());
            gameData.setTimeLimit(memoryConfig.getTimeLimit());
            gameData.setMaxMoves(memoryConfig.getMaxMoves());
            gameData.setCreateTime(LocalDateTime.now());
            
            MemoryGameResult result = new MemoryGameResult();
            result.setSuccess(true);
            result.setGameData(gameData);
            result.setEstimatedTime(calculateMemoryGameTime(memoryConfig));
            result.setMaxScore(calculateMemoryGameScore(memoryConfig));
            
            return result;
            
        } catch (Exception e) {
            log.error("创建记忆游戏失败", e);
            return createMemoryGameErrorResult("创建失败: " + e.getMessage());
        }
    }

    /**
     * 创建图片涂色游戏
     *
     * @param imageUrl 原图URL
     * @param coloringConfig 涂色配置
     * @return 涂色游戏数据
     */
    public static ColoringGameResult createColoringGame(String imageUrl, ColoringGameConfig coloringConfig) {
        try {
            log.info("创建图片涂色游戏: {}", imageUrl);
            
            BufferedImage originalImage = ImageIO.read(new URL(imageUrl));
            
            // 1. 生成线稿
            BufferedImage lineArt = generateLineArt(originalImage, coloringConfig);
            
            // 2. 分割涂色区域
            List<ColoringRegion> regions = segmentColoringRegions(lineArt, coloringConfig);
            
            // 3. 生成调色板
            List<Color> palette = generateColorPalette(originalImage, coloringConfig);
            
            // 4. 创建游戏数据
            ColoringGameData gameData = new ColoringGameData();
            gameData.setGameId(IdUtil.fastSimpleUUID());
            gameData.setOriginalImageUrl(imageUrl);
            gameData.setLineArtData(imageToBytes(lineArt));
            gameData.setColoringRegions(regions);
            gameData.setColorPalette(palette);
            gameData.setDifficulty(coloringConfig.getDifficulty());
            gameData.setCreateTime(LocalDateTime.now());
            
            ColoringGameResult result = new ColoringGameResult();
            result.setSuccess(true);
            result.setGameData(gameData);
            result.setRecommendedColors(extractRecommendedColors(originalImage));
            
            return result;
            
        } catch (Exception e) {
            log.error("创建涂色游戏失败: {}", imageUrl, e);
            return createColoringGameErrorResult("创建失败: " + e.getMessage());
        }
    }

    /**
     * 创建互动式图片故事
     *
     * @param imageUrls 图片URL列表
     * @param storyConfig 故事配置
     * @return 互动故事数据
     */
    public static InteractiveStoryResult createInteractiveStory(List<String> imageUrls, InteractiveStoryConfig storyConfig) {
        try {
            log.info("创建互动式图片故事: {} 个场景", imageUrls.size());
            
            // 1. 分析图片内容
            List<SceneAnalysis> sceneAnalyses = analyzeScenes(imageUrls);
            
            // 2. 生成故事情节
            List<StoryScene> scenes = generateStoryScenes(sceneAnalyses, storyConfig);
            
            // 3. 创建选择分支
            Map<String, List<StoryChoice>> choices = generateStoryChoices(scenes, storyConfig);
            
            // 4. 生成背景音乐建议
            List<String> musicSuggestions = generateMusicSuggestions(scenes);
            
            InteractiveStoryData storyData = new InteractiveStoryData();
            storyData.setStoryId(IdUtil.fastSimpleUUID());
            storyData.setTitle(storyConfig.getTitle());
            storyData.setScenes(scenes);
            storyData.setChoices(choices);
            storyData.setMusicSuggestions(musicSuggestions);
            storyData.setGenre(storyConfig.getGenre());
            storyData.setCreateTime(LocalDateTime.now());
            
            InteractiveStoryResult result = new InteractiveStoryResult();
            result.setSuccess(true);
            result.setStoryData(storyData);
            result.setEstimatedPlayTime(calculateStoryPlayTime(scenes));
            result.setComplexityLevel(calculateStoryComplexity(scenes, choices));
            
            return result;
            
        } catch (Exception e) {
            log.error("创建互动故事失败", e);
            return createInteractiveStoryErrorResult("创建失败: " + e.getMessage());
        }
    }

    // ==================== 私有辅助方法 ====================

    /**
     * 切割图片为拼图块
     */
    private static List<PuzzlePiece> cutImageIntoPieces(BufferedImage image, PuzzleConfig config) {
        List<PuzzlePiece> pieces = new ArrayList<>();
        int pieceWidth = image.getWidth() / config.getCols();
        int pieceHeight = image.getHeight() / config.getRows();
        
        for (int row = 0; row < config.getRows(); row++) {
            for (int col = 0; col < config.getCols(); col++) {
                BufferedImage pieceImage = image.getSubimage(
                    col * pieceWidth, row * pieceHeight, pieceWidth, pieceHeight);
                
                PuzzlePiece piece = new PuzzlePiece();
                piece.setId(row * config.getCols() + col);
                piece.setCorrectRow(row);
                piece.setCorrectCol(col);
                piece.setCurrentRow(row);
                piece.setCurrentCol(col);
                piece.setImageData(imageToBytes(pieceImage));
                
                pieces.add(piece);
            }
        }
        
        return pieces;
    }

    /**
     * 生成拼图预览
     */
    private static byte[] generatePuzzlePreview(List<PuzzlePiece> pieces, PuzzleConfig config) {
        try {
            BufferedImage preview = new BufferedImage(400, 300, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = preview.createGraphics();
            g2d.setColor(Color.LIGHT_GRAY);
            g2d.fillRect(0, 0, 400, 300);
            
            // 绘制网格
            g2d.setColor(Color.DARK_GRAY);
            int cellWidth = 400 / config.getCols();
            int cellHeight = 300 / config.getRows();
            
            for (int i = 0; i <= config.getCols(); i++) {
                g2d.drawLine(i * cellWidth, 0, i * cellWidth, 300);
            }
            for (int i = 0; i <= config.getRows(); i++) {
                g2d.drawLine(0, i * cellHeight, 400, i * cellHeight);
            }
            
            g2d.dispose();
            return imageToBytes(preview);
        } catch (Exception e) {
            log.error("生成拼图预览失败", e);
            return new byte[0];
        }
    }

    /**
     * 创建修改后的图片（找茬用）
     */
    private static BufferedImage createModifiedImage(BufferedImage original, SpotDifferenceConfig config) {
        BufferedImage modified = new BufferedImage(original.getWidth(), original.getHeight(), original.getType());
        Graphics2D g2d = modified.createGraphics();
        g2d.drawImage(original, 0, 0, null);
        
        // 随机添加差异点
        Random random = new Random();
        for (int i = 0; i < config.getDifferenceCount(); i++) {
            int x = random.nextInt(original.getWidth() - 50);
            int y = random.nextInt(original.getHeight() - 50);
            
            // 随机选择修改类型
            switch (random.nextInt(3)) {
                case 0: // 添加圆形
                    g2d.setColor(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)));
                    g2d.fillOval(x, y, 20, 20);
                    break;
                case 1: // 添加矩形
                    g2d.setColor(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)));
                    g2d.fillRect(x, y, 25, 15);
                    break;
                case 2: // 模糊区域
                    // 简单的模糊效果
                    g2d.setColor(Color.WHITE);
                    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
                    g2d.fillRect(x, y, 30, 30);
                    break;
            }
        }
        
        g2d.dispose();
        return modified;
    }

    /**
     * 图片转字节数组
     */
    private static byte[] imageToBytes(BufferedImage image) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "PNG", baos);
            return baos.toByteArray();
        } catch (IOException e) {
            log.error("图片转换失败", e);
            return new byte[0];
        }
    }

    /**
     * 计算预估时间
     */
    private static int calculateEstimatedTime(PuzzleConfig config) {
        int totalPieces = config.getRows() * config.getCols();
        return totalPieces * 30; // 每块30秒
    }

    /**
     * 计算最高分数
     */
    private static int calculateMaxScore(PuzzleConfig config) {
        int totalPieces = config.getRows() * config.getCols();
        return totalPieces * 100;
    }

    // 其他辅助方法的模拟实现
    private static List<DifferencePoint> generateDifferences(BufferedImage image, SpotDifferenceConfig config) { return new ArrayList<>(); }
    private static List<String> generateHints(List<DifferencePoint> differences) { return new ArrayList<>(); }
    private static Map<String, Object> generateEffectParameters(ARFilterConfig config) { return new HashMap<>(); }
    private static byte[] generate3DModelData(ARFilterConfig config) { return new byte[0]; }
    private static String generateVertexShader(ARFilterConfig config) { return "// Vertex shader code"; }
    private static String generateFragmentShader(ARFilterConfig config) { return "// Fragment shader code"; }
    private static byte[] generateFilterPreview(ARFilterConfig config) { return new byte[0]; }
    private static List<BodyKeypoint> detectBodyPose(BufferedImage image) { return new ArrayList<>(); }
    private static BufferedImage loadClothingImage(String url) { return new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); }
    private static BufferedImage fitClothingToBody(BufferedImage clothing, List<BodyKeypoint> keypoints, VirtualTryOnConfig config) { return clothing; }
    private static BufferedImage compositeImages(BufferedImage user, BufferedImage clothing, List<BodyKeypoint> keypoints) { return user; }
    private static BufferedImage postProcessTryOn(BufferedImage image, VirtualTryOnConfig config) { return image; }
    private static double calculateFitScore(List<BodyKeypoint> keypoints, VirtualTryOnConfig config) { return 0.85; }
    private static List<String> selectGameImages(List<String> imageUrls, int count) { return imageUrls.subList(0, Math.min(count, imageUrls.size())); }
    private static List<MemoryCard> createMemoryCards(List<String> images) { return new ArrayList<>(); }
    private static int calculateMemoryGameTime(MemoryGameConfig config) { return 300; }
    private static int calculateMemoryGameScore(MemoryGameConfig config) { return 1000; }
    private static BufferedImage generateLineArt(BufferedImage image, ColoringGameConfig config) { return image; }
    private static List<ColoringRegion> segmentColoringRegions(BufferedImage image, ColoringGameConfig config) { return new ArrayList<>(); }
    private static List<Color> generateColorPalette(BufferedImage image, ColoringGameConfig config) { return new ArrayList<>(); }
    private static List<Color> extractRecommendedColors(BufferedImage image) { return new ArrayList<>(); }
    private static List<SceneAnalysis> analyzeScenes(List<String> imageUrls) { return new ArrayList<>(); }
    private static List<StoryScene> generateStoryScenes(List<SceneAnalysis> analyses, InteractiveStoryConfig config) { return new ArrayList<>(); }
    private static Map<String, List<StoryChoice>> generateStoryChoices(List<StoryScene> scenes, InteractiveStoryConfig config) { return new HashMap<>(); }
    private static List<String> generateMusicSuggestions(List<StoryScene> scenes) { return new ArrayList<>(); }
    private static int calculateStoryPlayTime(List<StoryScene> scenes) { return 600; }
    private static String calculateStoryComplexity(List<StoryScene> scenes, Map<String, List<StoryChoice>> choices) { return "medium"; }

    // 错误结果创建方法
    private static PuzzleGameResult createPuzzleErrorResult(String error) { 
        PuzzleGameResult result = new PuzzleGameResult(); 
        result.setSuccess(false); 
        return result; 
    }
    private static SpotDifferenceResult createSpotDifferenceErrorResult(String error) { return new SpotDifferenceResult(); }
    private static ARFilterResult createARFilterErrorResult(String error) { return new ARFilterResult(); }
    private static VirtualTryOnResult createVirtualTryOnErrorResult(String error) { return new VirtualTryOnResult(); }
    private static MemoryGameResult createMemoryGameErrorResult(String error) { return new MemoryGameResult(); }
    private static ColoringGameResult createColoringGameErrorResult(String error) { return new ColoringGameResult(); }
    private static InteractiveStoryResult createInteractiveStoryErrorResult(String error) { return new InteractiveStoryResult(); }
}
